package isssr.bean.boundary;

import isssr.bean.entity.GoalStatus;
import isssr.bean.entity.OrganizationalGoal;
import isssr.bean.entity.Role;
import isssr.bean.entity.User;
import isssr.bean.utility.StorageUtility;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;

public class LazyOrgGoalDataModel extends LazyDataModel<OrganizationalGoal> implements
		Serializable {

	private class LazyGoalComparator implements Comparator
	{
		private SortOrder order;
		private String field;

		protected LazyGoalComparator(String field, SortOrder order)
		{
			this.field=field;
			this.order=order;
		}
		
		@Override
		public int compare(Object arg0, Object arg1) {
			
			OrganizationalGoal goal0 = (OrganizationalGoal) arg0;
			OrganizationalGoal goal1 = (OrganizationalGoal) arg1;
			
			System.out.println("ordertype " + (this.order == SortOrder.ASCENDING ? "ascen" : (this.order == SortOrder.DESCENDING ? "descen" : "unord")) );
			System.out.println("orderfield " + this.field);
			if(this.order == SortOrder.UNSORTED)
				return 0;
			
			if(this.field.equals("title"))
			{
				return compareString(goal0.getTitle(), goal1.getTitle());
			}
			else if(this.field.equals("status"))
			{
				return compareStatus(goal0.getStatus(), goal1.getStatus());
			}
			
			return 0;
		}

		private int compareStatus(Integer status0, Integer status1) {
			Integer numericOrder = status0 == status1 ? 0 : ( status0 < status1 ? -1 : 1 );
			
			return correctOrdering(numericOrder);
		}

		private int compareString(String arg0, String arg1) {
			
			int lexicographicalOrder = arg0.compareTo(arg1);
			int normalizedOrder;
			
			if(lexicographicalOrder > 0)
				normalizedOrder = 1;
			else if(lexicographicalOrder < 0)
				normalizedOrder = -1;
			else
				normalizedOrder = 0;
			
			return correctOrdering(normalizedOrder);
			
		}

		private int correctOrdering(int order) {
			
			int finalOrder;
			
			switch(this.order)
			{
			case ASCENDING:
				finalOrder = order;
				break;
			case DESCENDING:
				finalOrder = (order * -1);
				break;
			default:
				finalOrder = 0;
				break;
			}
			
			System.out.println("ordered: " + finalOrder);
			
			return finalOrder;
		}
		
	}
	
	private ArrayList<OrganizationalGoal> fetchedGoal;
	
	private HashMap<String, String> labelConversion;

	private User currentUser;

	private HashMap<String, GoalStatus> statusMapping;
	
	public LazyOrgGoalDataModel(User currentUser)
	{
		this.currentUser = currentUser;
		this.fetchedGoal = new ArrayList<OrganizationalGoal>();
		this.statusMapping = new HashMap<String, GoalStatus>();
		
		updateStatusMapping();
	}
	
	private void updateStatusMapping() {

		this.statusMapping.put("In Definition", GoalStatus.DEFINITION);
		this.statusMapping.put("Elicitation Vote", GoalStatus.ELICITATION_VOTE);
		this.statusMapping.put("Feasibility Analysis", GoalStatus.FEASIBILITY_ANALYSIS);
		this.statusMapping.put("In Developement", GoalStatus.DEVELOPEMENT);
		this.statusMapping.put("Completed", GoalStatus.COMPLETED);
		
	}

	@Override  
    public Object getRowKey(OrganizationalGoal goal) {  
        return goal.getId();  
    }
	
	@Override  
    public OrganizationalGoal getRowData(String rowKey) {  
		
		Integer goalID;
		
		for(OrganizationalGoal goal : this.fetchedGoal) {  
            
			goalID = Integer.parseInt(rowKey);
			
			if(goal.getId().equals(goalID))  
			{
				return goal;  
			}  
		}
        return null;  
    }  
	
	private Role loadRole(String title)
	{
		Role prototypeRole = new Role(), resultRole = null;
		if(title != null)
		{
			prototypeRole.setTitle(title);
			
			try
			{
				Iterator<Role> role_it = (Iterator<Role>) prototypeRole.loadSiblings();
				if(role_it.hasNext())
				{
					resultRole = role_it.next();
				}
			}
			catch(Exception ex)
			{
				ex.printStackTrace();
			}
			
		}
		
		return resultRole;
	}
	
	
	@Override
	public List<OrganizationalGoal> load(int firstRecord, int pageSize, String sortField, SortOrder sortOrder,
			Map<String, String> filters) {
		Iterator<OrganizationalGoal> it = StorageUtility.getGoalsByOwner(this.currentUser);
		ArrayList<OrganizationalGoal> goalList = new ArrayList<OrganizationalGoal>();
		
		while(it.hasNext())
		{
			goalList.add(it.next());
		} 
		
		System.out.println("record number: " + goalList.size());
		
		ArrayList<OrganizationalGoal> tempList;
		this.fetchedGoal = goalList;
		
		tempList = filterList(goalList, filters);
		
		setRowCount(tempList.size());
		
		if(sortField != null) {  
			LazyGoalComparator comparator = new LazyGoalComparator(sortField, sortOrder); 
            Collections.sort(tempList, comparator);  
        }  
		
		return tempList;
		
	}
	
	private ArrayList<OrganizationalGoal> filterList(ArrayList<OrganizationalGoal> goalList,
			Map<String, String> filters) {
		ArrayList<OrganizationalGoal> filteredList = (ArrayList<OrganizationalGoal>) goalList.clone();
		
		for(Entry<String, String> e : filters.entrySet())
		{
			if(e.getKey().equals("title"))
			{
				for(OrganizationalGoal goal : goalList)
				{
					if(!goal.getTitle().equals((String)e.getValue()))
					{
						filteredList.remove(goal);
					}
				}
			}
			else if(e.getKey().equals("status"))
			{
				GoalStatus goalStatusFilter = getEnumStatusFromFilter(e.getValue());
				for(OrganizationalGoal goal : goalList)
				{
					if(goal.getEnumStatus() != goalStatusFilter)
					{
						filteredList.remove(goal);
					}
				}
			}
		}
		return filteredList;
	}

	private GoalStatus getEnumStatusFromFilter(String filterValue) {
		
		GoalStatus status = this.statusMapping.get(filterValue);
		
		return status;
	}

}
